深色模式 (Dark Mode) 在近代使用者裝置上顯得越來越普遍,iOS、MacOS、Android、Windows 在更新上都不約而同的推出。長時間暴露在高亮度的白底介面中,往往容易造成眼睛疲勞、乾澀,甚至影響專注力與睡眠品質。為了改善這樣的使用體驗,深色模式誕生了。
或許不見得要一開始就導入深色模式,但若有提供這個啟閉選項,在使用者的體驗上肯定是更好的。想先列出幾個優點以及需要顧慮的點。
優點:
缺點:
這邊以 Next.js 作為示範,若有需要在 Vite、Astro、Remix 上實作,可以參考 Shadcn/ui Dark Mode。
專案中安裝 next-themes、Shadcn/ui 的 Button、Dropdown Menu、lucide-icon
npm install next-themes
npx shadcn@latest add "https://animate-ui.com/r/icon.json"
npx shadcn@latest add button dropdown-menu
在 components 資料夾,新增 theme-provider.tsx 檔案,並加上以下程式碼
若沒有
components資料夾,可以在專案目錄中新增
"use client"
import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
export function ThemeProvider({
    children,
    ...props
    }: React.ComponentProps<typeof NextThemesProvider>) {
        return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}

修改 app/layout.tsx
在 import 區域增加
import { ThemeProvider } from "@/components/theme-provider"

並且在 export default function RootLayout(...){return(...)} 中修改
export default function RootLayout({ children }: RootLayoutProps) {
    return (
        <>
        <html lang="zh-Hant" suppressHydrationWarning>
            <head />
            <body>
            <ThemeProvider
                attribute="class"
                defaultTheme="system"
                enableSystem
                disableTransitionOnChange
            >
                {children}
            </ThemeProvider>
            </body>
        </html>
        </>
    )
}

找個合適的位置放置深淺色模式切換。在這邊的範例中,我將切換按鈕放在 next.js logo 下方。
打開 app/page.tsx,並且將必要的 import 載入
找到 export function ...{} 當中加入這個 React Hook,用途是後面要 onclick 動作時可以觸發
const { setTheme } = useTheme()

在 return(<html>...</html>) 中加入深淺色模式切換按鈕和 Menu
<DropdownMenu>
    <DropdownMenuTrigger asChild>
        <Button variant="outline" size="icon">
        <Sun className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" />
        <Moon className="absolute h-[1.2rem] w-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" />
        <span className="sr-only">Toggle theme</span>
        </Button>
    </DropdownMenuTrigger>
    <DropdownMenuContent align="end">
        <DropdownMenuItem onClick={() => setTheme("light")}>
        Light
        </DropdownMenuItem>
        <DropdownMenuItem onClick={() => setTheme("dark")}>
        Dark
        </DropdownMenuItem>
        <DropdownMenuItem onClick={() => setTheme("system")}>
        System
        </DropdownMenuItem>
    </DropdownMenuContent>
</DropdownMenu>

執行 npm run dev 測試效果

今天示範如何完成深淺色模式的設置,並且觀察在切換深淺色時使用 onClick 事件的運作方式。其實不只 dropdown menu,還能夠透過 switch、icon 等不同元件來實現切換。以上算是最基礎的範例,幫助大家建立概念。
明天我們將進一步探索 Animate UI 的文字動畫效果,看看如何讓文字活起來~
雖然平常還是喜歡白色但用久了真的需要深色mode突然眼睛變得好舒服哈
沒錯 適時的切換讓頭腦清醒一下🤣
長時間暴露在高亮度的白底介面中,往往容易造成眼睛疲勞、乾澀,甚至影響專注力與睡眠品質。
聽起來像是筆者本人的親身經歷
被發現了哈哈 所以才更想要推廣對使用者面向的網頁、App 都具備深淺色切換🥳
真厲害